<?php

use LucaDegasperi\OAuth2Server\Authorizer;
use Rootant\Api\Exception\ValidationException;
use Rootant\Api\Exception\ResourceNonExistentException;

class UserController extends CommonController
{
    public function __construct(Authorizer $authorizer)
    {
        parent::__construct($authorizer);
        $this->beforeFilter('oauth', ['except' => ['store', 'fetchEntry']]);
        $this->beforeFilter('oauth.checkClient', ['only' => 'store']);
        $this->beforeFilter('validation');
        $this->afterFilter('disconnect:mysql', ['only' => ['store', 'show', 'modify']]);
        $this->afterFilter('disconnect:major', ['only' => ['hasNewInformation', 'removeNotice', 'store', 'modify', 'logout', 'myComment', 'myStar', 'myInformation']]);
    }

    private static $_validate = [
        'store' => [
            'username' => 'required|min:5|unique:user,name',
            'email'    => 'required|email|unique:user',
            'password' => 'required|min:6|confirmed',
        ],
    ];

    public function store()
    {
        $email    = Input::get('email');
        $password = Input::get('password');

        $avatarUrl = $this->getAvatarUrl();

        $insertData = array(
                'name'        => Input::get('username'),
                'avatar_url'  => $avatarUrl,
                'password'    => md5($password),
                'email'       => $email,
                'personal_id' => MultiplexController::uuid(),
            );

        $user = DB::table('user');

        $insertId = $user->insertGetId($insertData);
        // 绑定第三方登录用户的信息
        $this->bindThirdPartyUser($email, $password);

        $this->preserve($email, $password);

        return (array) $user->find($insertId);
    }

    protected function getAvatarUrl()
    {
        $avatarUrl = Config::get('imagecache::paths.avatar_url_prefix').'/default.png';

        if (!Input::has('avatar_url')) {
            return $avatarUrl;
        }

        $avatar = Input::get('avatar_url');

        if (preg_match('#^http(s)?://#', $avatar) === 1) {
            $avatarUrl = $avatar;
        }

        return $avatarUrl;
    }

    protected function preserve($username, $password)
    {
        if (! Input::has('unionid')) {
            return;
        }

        $data = [
            'id' => Input::get('unionid'),
            'username' => $username,
            'password' => $password,
        ];

        $authorization = new Authorization;
        $authorization->createOrUpdate($data);
    }

    /**
     * [bindThirdPartyUser description]
     * @param  string $username 用户名
     * @param  string $password 密码
     * @return void
     */
    protected function bindThirdPartyUser($username, $password)
    {
        if (!Input::has('token')) {
            return;
        }

        $token = Input::get('token');

        if (strlen($token) !== 30) {
            return;
        }

        $insertData = array(
                'token'      => $token,
                'username'   => $username,
                'password'   => $password,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            );

        $this->dbRepository('major', 'third_party_user_token')->insert($insertData);
    }

    public function logout()
    {
        $oauthAccessToken = $this->dbRepository('major', 'oauth_access_tokens');

        $oauthAccessToken->where('id', $this->accessToken)->delete();

        return Response::make('', 204);
    }

    public function myComment()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $comment = $this->dbRepository('major', 'journal_comment');
        $commentModel = $comment->where('user_id', $uid)
            ->orderBy('created_at', 'desc');
        // 增加数据分页
        $this->addPagination($commentModel);

        $returnData = $commentModel->get();

        $comments = $this->processCommentResponse($returnData);

        foreach ($comments as $comment) {
            $comment->flag = 3;
            $comment->journal = $this->getJournalById($comment->journal_id);
        }

        return $comments;
    }

    public function myStar()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $starModel = $this->dbRepository('major', 'star')
            ->where('user_id', $uid)
            ->latest('created_at');
        // 增加分页
        $this->addPagination($starModel);
        $idArr = $starModel->lists('journal_id');

        if (empty($idArr)) {
            return [];
        }

        $journals = array();
        foreach ($idArr as $id) {
            $journals[] = $this->getJournalById($id);
        }

        return $journals;
    }

    public function show()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        return (array) $this->user()->find($uid);
    }

    public function myInformation()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $model = $this->dbRepository('major', 'information')
            ->select('id', 'from_uid', 'from_user_ip', 'created_at', 'content', 'type')
            ->where('to_uid', $uid)
            ->orderBy('created_at', 'desc');

        $this->addPagination($model);

        $information = $model->get();

        return $this->processMyInformation($information);
    }

    protected function processMyInformation($information)
    {
        foreach ($information as $v) {
            $this->userId = $v->from_uid;
            $this->userIp = $v->from_user_ip;
            $user = $this->getOwner();
            $user->display_name = $user->name;
            $v->user = $user;

            if ($v->type === 0) {
                // 消息为系统消息
                $v->content_info = ['system' => $v->content];
            } else {
                // 消息是序列化后的消息，则需要反序列
                $v->content_info = unserialize($v->content);
            }
        }

        foreach ($information as $v) {
            unset($v->from_uid, $v->from_user_ip, $v->type, $v->content);
        }

        return $information;
    }

    protected function validateModify($uid)
    {
        $rules = array(
                'name'  => 'min:5|unique:user,name,'.$uid,
                'email' => 'email|unique:user,email,'.$uid,
            );
        $validator = Validator::make(Input::all(), $rules);

        if ($validator->fails()) {
            throw new ValidationException($validator->messages()->all());
        }
    }

    public function modify()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $this->email = DB::table('user')->where('id', $uid)->pluck('email');

        $this->validateModify($uid);

        $user = User::find($uid);

        $allowedFields = ['avatar_url', 'name', 'email', 'address'];

        array_walk($allowedFields, function($item) use ($user, $uid) {
            $v = Input::get($item);
            if ($v && $item !== 'avatar_url') {
                $user->$item = $v;
            }
            if ($item === 'email' && Input::has('email')) {
                $this->updateThirdPartyUser($this->email, Input::get('email'));
            }
            if ($item === 'avatar_url' && Input::has('avatar_url')) {
                $user->avatar_url = $this->updateAvatar($uid);
            }
        });

        $user->save();

        return $user;
    }

    /**
     * 更新用户头像
     *
     * @param  string $uid 用户id
     * @return string
     */
    protected function updateAvatar($uid)
    {
        $imageStr = Input::get('avatar_url');

        $subDir = substr($uid, -1);
        $storgePath = Config::get('imagecache::paths.avatar_url_prefix').'/'.$subDir;

        $path = public_path().$storgePath;
        $path = str_replace('\\', '/', $path);
        if (!is_dir($path)) {
            @mkdir($path, 0777, true);
        }

        $matchFlag = preg_match('/^(data:\s*image\/(\w+);base64,)/', $imageStr, $matches);
        if (!$matchFlag) {
            throw new ApiException;
        }

        $ext = $matches[2];
        $fileName = $path.'/'.$uid.'.'.$ext;
        $flag = file_put_contents($fileName, base64_decode(str_replace($matches[1], '', $imageStr)));
        if ($flag === false) {
            throw new ValidationException('上传头像发生错误');
        }

        $newAvatarUrl = $storgePath.'/'.$uid.'.'.$ext;

        $this->updateCommentUserAvatar($uid, $newAvatarUrl);

        return $newAvatarUrl;
    }

    protected function updateCommentUserAvatar($uid, $newAvatarUrl)
    {
        $content = DB::connection('major')
            ->table('information')
            ->where('to_uid', '=', $uid)
            ->lists('content', 'id');

        if (empty($content)) {
            return;
        }

        foreach ($content as $key => &$value) {
            $origin = unserialize($value);

            $data = $origin['comment'];
            foreach ($data as $v) {
                if (is_object($v) && $v->avatar_url !== '/uploads/images/avatar/default.png') {
                    unset($content[$key]);
                    continue;
                }

                if (is_object($v) && $v->avatar_url === '/uploads/images/avatar/default.png') {
                    $v->avatar_url = $newAvatarUrl;
                }
            }

            $value = serialize(['reply' => $origin['reply'], 'comment' => $data]);
        }
        unset($value);

        foreach ($content as $key => $value) {
            DB::connection('major')
                ->table('information')
                ->where('id', '=', $key)
                ->update(['content' => $value, 'updated_at' => date('Y-m-d H:i:s')]);
        }
    }

    /**
     * [updateThirdPartyUser description]
     * @param  string $rawEmail 旧邮箱
     * @param  string $newEmail 新邮箱
     * @return void
     */
    protected function updateThirdPartyUser($rawEmail, $newEmail)
    {
        $this->dbRepository('major', 'third_party_user_token')
            ->where('username', $rawEmail)
            ->update(array('username' => $newEmail, 'updated_at' => date('Y-m-d H:i:s')));
    }

    /**
     * 用户是否有新消息
     *
     * @api get /v3/notices
     * @return array
     */
    public function hasNewInformation()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $flag = $this->dbRepository('major', 'information')
            ->where('unread_uid', $uid)
            ->exists();

        return array('new_information' => $flag);
    }

    /**
     * 点击小红点
     * 取消红点
     *
     * @api delete /v3/user/notices
     * @return object
     */
    public function removeNotice()
    {
        $uid = $this->authorizer->getResourceOwnerId();

        $updateData = array(
                'unread_uid' => 0,
                'updated_at' => date('Y-m-d H:i:s'),
            );

        $this->dbRepository('major', 'information')
            ->where('unread_uid', $uid)
            ->update($updateData);

        return Response::make('', 204);
    }

    public function fetchEntry($id)
    {
        $authorization = DB::connection('major')
            ->table('authorization')
            ->find($id, ['username', 'password']);

        if (! $authorization) {
            return [];
        }

        return (array) $authorization;
    }

}